<?php
//由于面向对象的关系（比如多态），会造成很多子类。这样会带来实例化子类的问题（比如到底实例化哪个子类？）！

//第一版老板类固定生成了某个员工对象，如果想生成其他类型的员工就会存在问题！
/*abstract class Employee{
    protected $name;
    function __construct($name)
    {
        $this->name = $name;
    }
}

class Minion extends Employee{
    public function fire(){
        print "{$this->name}:我马上走人";
    }
}

class NastyBoss{
    private $employees = array();
    function addEmployees($employeeName){
        $this->employees[] = new Minion($employeeName);
    }
    function projectFails(){
        if(count($this->employees)>0){
            $emp = array_pop($this->employees);
            $emp->fire();
        }
    }
}

$boss = new NastyBoss();
$boss->addEmployees('张三');
$boss->addEmployees('李四');
$boss->addEmployees('王五');
$boss->projectFails();*/

//第二版，把老板类里面的添加员工，传入名字，改成传入对象，虽然可以添加多个类型的员工，但是客户端代码还是需要实例多个员工类！
/*abstract class Employee{
    protected $name;
    function __construct($name)
    {
        $this->name = $name;
    }
}

class Minion extends Employee{
    public function fire(){
        print "{$this->name}:我马上走人\n";
    }
}

class CluedUp extends Employee{
    public function fire(){
        print "{$this->name}:我打电话叫我的律师\n";
    }
}

class NastyBoss{
    private $employees = array();
    function addEmployees(Employee $employeeName){
        $this->employees[] = $employeeName;
    }
    function projectFails(){
        if(count($this->employees)>0){
            $emp = array_pop($this->employees);
            $emp->fire();
        }
    }
}

$boss = new NastyBoss();
$boss->addEmployees(new Minion('张三'));
$boss->addEmployees(new CluedUp('李四'));
$boss->addEmployees(new Minion('王五'));
$boss->projectFails();
$boss->projectFails();
$boss->projectFails();*/

//第三个版本，创建一个生成对象的方法，实际就是工厂方法

abstract class Employee{
    protected $name;
    private static $types = array('minion','cluedUp','wellconnected');
    public static function recruit($name){
        $num = rand(1,count(self::$types))-1;
        $class = self::$types[$num];
        return new $class($name);
    }
    function __construct($name)
    {
        $this->name = $name;
    }
}

class Minion extends Employee{
    public function fire(){
        print "{$this->name}:我马上走人\n";
    }
}

class CluedUp extends Employee{
    public function fire(){
        print "{$this->name}:我打电话叫我的律师\n";
    }
}

class WellConnected extends Employee{
    public function fire(){
        print "{$this->name}:我叫我兄弟\n";
    }
}

class NastyBoss{
    private $employees = array();
    function addEmployees(Employee $employeeName){
        $this->employees[] = $employeeName;
    }
    function projectFails(){
        if(count($this->employees)>0){
            $emp = array_pop($this->employees);
            $emp->fire();
        }
    }
}
$boss = new NastyBoss();
$boss->addEmployees(Employee::recruit('张三'));
$boss->addEmployees(Employee::recruit('李四'));
$boss->addEmployees(Employee::recruit('王五'));
/*$aa = new cluedup('aa');
var_dump($aa);exit;*/
$boss->projectFails();
$boss->projectFails();
$boss->projectFails();